package main.java.com.healthy.dao.impl;


import main.java.com.healthy.dao.DietRecordDAO;
import main.java.com.healthy.entity.DietRecord;
import main.java.com.healthy.util.FileUtil;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 饮食记录数据访问实现类
 */
public class DietRecordDAOImpl implements DietRecordDAO {

    private static final String RECORD_DIR = "data/diet_records/";
    private static final String RECORD_FILE_PREFIX = "records_";

    // 内存缓存，提高性能
    private Map<String, List<DietRecord>> userRecordsCache = new HashMap<>();

    public DietRecordDAOImpl() {
        // 初始化时不需要加载所有记录，按需加载
    }

    @Override
    public boolean addRecord(DietRecord record) {
        try {
            String userId = record.getUserId();
            List<DietRecord> records = getUserRecords(userId);
            records.add(record);
            return saveUserRecords(userId, records);
        } catch (Exception e) {
            System.err.println("添加饮食记录失败: " + e.getMessage());
            return false;
        }
    }

    @Override
    public boolean updateRecord(DietRecord record) {
        try {
            String userId = record.getUserId();
            List<DietRecord> records = getUserRecords(userId);

            for (int i = 0; i < records.size(); i++) {
                if (records.get(i).getRecordId().equals(record.getRecordId())) {
                    records.set(i, record);
                    return saveUserRecords(userId, records);
                }
            }
            return false;
        } catch (Exception e) {
            System.err.println("更新饮食记录失败: " + e.getMessage());
            return false;
        }
    }

    @Override
    public boolean deleteRecord(String recordId) {
        try {
            // 需要先找到记录所属的用户
            for (String userId : userRecordsCache.keySet()) {
                List<DietRecord> records = userRecordsCache.get(userId);
                boolean removed = records.removeIf(record -> record.getRecordId().equals(recordId));
                if (removed) {
                    return saveUserRecords(userId, records);
                }
            }

            // 如果缓存中没有，需要搜索所有用户文件
            // 这里简化处理，实际项目中可能需要更复杂的逻辑
            return false;
        } catch (Exception e) {
            System.err.println("删除饮食记录失败: " + e.getMessage());
            return false;
        }
    }

    @Override
    public DietRecord getRecordById(String recordId) {
        // 在缓存中查找
        for (List<DietRecord> records : userRecordsCache.values()) {
            Optional<DietRecord> record = records.stream()
                    .filter(r -> r.getRecordId().equals(recordId))
                    .findFirst();
            if (record.isPresent()) {
                return record.get();
            }
        }
        return null;
    }

    @Override
    public List<DietRecord> getRecordsByUserAndDate(String userId, LocalDate date) {
        List<DietRecord> records = getUserRecords(userId);
        return records.stream()
                .filter(record -> record.getRecordDate().equals(date))
                .sorted((r1, r2) -> Integer.compare(r1.getMealTypeCode(), r2.getMealTypeCode()))
                .collect(Collectors.toList());
    }

    @Override
    public List<DietRecord> getRecordsByUserAndDateRange(String userId, LocalDate startDate, LocalDate endDate) {
        List<DietRecord> records = getUserRecords(userId);
        return records.stream()
                .filter(record -> !record.getRecordDate().isBefore(startDate) &&
                        !record.getRecordDate().isAfter(endDate))
                .sorted(Comparator.comparing(DietRecord::getRecordDate)
                        .thenComparing(DietRecord::getMealTypeCode))
                .collect(Collectors.toList());
    }

    @Override
    public List<DietRecord> getRecordsByUserAndMealType(String userId, LocalDate date, String mealType) {
        List<DietRecord> records = getUserRecords(userId);
        return records.stream()
                .filter(record -> record.getRecordDate().equals(date) &&
                        record.getMealType().equals(mealType))
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Double> calculateDailyNutrition(String userId, LocalDate date) {
        List<DietRecord> dailyRecords = getRecordsByUserAndDate(userId, date);

        Map<String, Double> nutrition = new HashMap<>();
        nutrition.put("calories", 0.0);
        nutrition.put("carbohydrates", 0.0);
        nutrition.put("protein", 0.0);
        nutrition.put("fat", 0.0);
        nutrition.put("fiber", 0.0);

        for (DietRecord record : dailyRecords) {
            nutrition.put("calories", nutrition.get("calories") + record.getCalories());
            nutrition.put("carbohydrates", nutrition.get("carbohydrates") + record.getCarbohydrates());
            nutrition.put("protein", nutrition.get("protein") + record.getProtein());
            nutrition.put("fat", nutrition.get("fat") + record.getFat());
            nutrition.put("fiber", nutrition.get("fiber") + record.getFiber());
        }

        return nutrition;
    }

    @Override
    public Map<String, Double> calculateNutritionSummary(String userId, LocalDate startDate, LocalDate endDate) {
        List<DietRecord> records = getRecordsByUserAndDateRange(userId, startDate, endDate);

        Map<String, Double> summary = new HashMap<>();
        summary.put("totalCalories", 0.0);
        summary.put("totalCarbs", 0.0);
        summary.put("totalProtein", 0.0);
        summary.put("totalFat", 0.0);
        summary.put("totalFiber", 0.0);
        summary.put("averageCalories", 0.0);
        summary.put("averageCarbs", 0.0);
        summary.put("averageProtein", 0.0);
        summary.put("averageFat", 0.0);

        long days = startDate.until(endDate).getDays() + 1;

        for (DietRecord record : records) {
            summary.put("totalCalories", summary.get("totalCalories") + record.getCalories());
            summary.put("totalCarbs", summary.get("totalCarbs") + record.getCarbohydrates());
            summary.put("totalProtein", summary.get("totalProtein") + record.getProtein());
            summary.put("totalFat", summary.get("totalFat") + record.getFat());
            summary.put("totalFiber", summary.get("totalFiber") + record.getFiber());
        }

        if (days > 0) {
            summary.put("averageCalories", summary.get("totalCalories") / days);
            summary.put("averageCarbs", summary.get("totalCarbs") / days);
            summary.put("averageProtein", summary.get("totalProtein") / days);
            summary.put("averageFat", summary.get("totalFat") / days);
        }

        return summary;
    }

    @Override
    public List<LocalDate> getRecentRecordDates(String userId, int days) {
        List<DietRecord> records = getUserRecords(userId);
        LocalDate today = LocalDate.now();

        return records.stream()
                .map(DietRecord::getRecordDate)
                .distinct()
                .filter(date -> !date.isBefore(today.minusDays(days)))
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());
    }

    /**
     * 获取用户的饮食记录
     */
    @SuppressWarnings("unchecked")
    private List<DietRecord> getUserRecords(String userId) {
        // 先从缓存中获取
        if (userRecordsCache.containsKey(userId)) {
            return userRecordsCache.get(userId);
        }

        // 缓存中没有，从文件加载
        String filename = RECORD_DIR + RECORD_FILE_PREFIX + userId + ".dat";
        try {
            Object data = FileUtil.readObject(filename);
            if (data instanceof List) {
                List<DietRecord> records = (List<DietRecord>) data;
                userRecordsCache.put(userId, records);
                return records;
            } else {
                List<DietRecord> records = new ArrayList<>();
                userRecordsCache.put(userId, records);
                return records;
            }
        } catch (Exception e) {
            System.err.println("加载饮食记录失败: " + e.getMessage());
            List<DietRecord> records = new ArrayList<>();
            userRecordsCache.put(userId, records);
            return records;
        }
    }

    /**
     * 保存用户的饮食记录
     */
    private boolean saveUserRecords(String userId, List<DietRecord> records) {
        String filename = RECORD_DIR + RECORD_FILE_PREFIX + userId + ".dat";
        try {
            // 更新缓存
            userRecordsCache.put(userId, records);
            return FileUtil.writeObject(filename, records);
        } catch (Exception e) {
            System.err.println("保存饮食记录失败: " + e.getMessage());
            return false;
        }
    }
}